package com.cmonbaby.adapter.listview.base;

import androidx.collection.SparseArrayCompat;

import com.cmonbaby.adapter.listview.LViewHolder;

/**
 * ListView所有条目管理
 * @author simon 2016-9-13 上午11:16:29
 * @since JDK1.8 SDK6.0.1
 * @version V2.3.4
 * @param <T>
 */
public class LItemManager<T> {

    /**
     * 所有条目集合，相比较而言，安卓独有的SparseArrayCompat集合（Android开发中高效的数据结构用SparseArray代替HashMap）
     */
    private SparseArrayCompat<LItem<T>> styles = new SparseArrayCompat<>();

    /**
     * 获取所有item条目样式数量
     *
     * @return 条目样式数量
     */
    public int getItemViewStyleCount() {
        return styles.size();
    }

    /**
     * 加入一个新的item条目样式到item集合最末
     *
     * @param item 某item条目对象
     * @return ListView条目管理
     */
    public LItemManager<T> addStyle(LItem<T> item) {
        int viewType = styles.size(); // 避免每次都要调用计算集合长度
        if (item != null) {
            styles.put(viewType, item);
        }
        return this;
    }

    /**
     * 加入一个新的item条目到item集合中指定的位置
     *
     * @param viewType 指定位置
     * @param item 某item条目对象
     * @return ListView条目管理
     */
    public LItemManager<T> addStyle(int viewType, LItem<T> item) {
        if (styles.get(viewType) != null) { // 如果指定位置已有item条目，自动抛出异常
            throw new IllegalArgumentException(
                    "一个已经注册的视图类型为：" + viewType + ". 已经注册的ListViewItem为：" + styles.get(viewType));
        }
        styles.put(viewType, item);
        return this;
    }

    /**
     * 从item集合中移除一个指定条目
     *
     * @param item 某item条目对象
     * @return ListView条目管理
     */
    public LItemManager<T> removeDelegate(LItem<T> item) {
        if (item == null) { // 如果传入item条目为空，自动抛出异常
            throw new NullPointerException("ListView条目为空");
        }
        // 寻找传入移除的item条目位置，可能不存在
        int indexToRemove = styles.indexOfValue(item);

        if (indexToRemove >= 0) { // 当不等于-1，即存在该item条目时，调用removeAt(index)方法移除
            styles.removeAt(indexToRemove);
        }
        return this;
    }

    /**
     * 从item集合中移除一个指定位置的条目
     *
     * @param itemType 指定位置
     * @return ListView条目管理
     */
    public LItemManager<T> removeDelegate(int itemType) {
        // 寻找传入移除的item条目位置，可能不存在
        int indexToRemove = styles.indexOfKey(itemType);

        if (indexToRemove >= 0) { // 当不等于-1，即存在该item条目时，调用removeAt(index)方法移除
            styles.removeAt(indexToRemove);
        }
        return this;
    }


    /**
     * 根据数据源的position返回需要显示的的layout的type，type的值必须从0开始
     *
     * @param item 数据源对象
     * @param position 数据源的position
     * @return 需要显示的的layout的type
     */
    public int getItemViewType(T item, int position) {
        int stylesCount = styles.size(); // 避免每次都要调用计算集合长度
        for (int i = stylesCount - 1; i >= 0; i--) { // 倒序循环，避免增删集合抛出异常
            LItem<T> delegate = styles.valueAt(i);
            if (delegate.isForViewType(item, position)) { // 是否为当前样式显示，由外面实现
                return styles.keyAt(i);
            }
        }
        throw new IllegalArgumentException(
                "在数据源中指定的位置没有相匹配的ListViewItem，position=" + position);
    }

    /**
     * 视图与数据源绑定显示，有ViewHolder，T实体对象，条目位置
     *
     * @param holder LViewHolder
     * @param item 数据源对象
     * @param position 数据源的position
     */
    public void convert(LViewHolder holder, T item, int position) {
        int delegatesCount = styles.size(); // 避免每次都要调用计算集合长度
        for (int i = 0; i < delegatesCount; i++) { // 倒序循环，避免增删集合抛出异常
            LItem<T> delegate = styles.valueAt(i);

            if (delegate.isForViewType(item, position)) {
                delegate.convert(holder, item, position); // 视图与数据源绑定显示，由外面实现
                return;
            }
        }
        throw new IllegalArgumentException(
                "在数据源中指定的位置没有相匹配的ListViewItemManager，position=" + position);
    }


    public int getItemViewLayoutId(int viewType) {
        return styles.get(viewType).getItemViewLayoutId();
    }

    public int getItemViewType(LItem lItem) {
        return styles.indexOfValue(lItem);
    }

    /**
     * 每绘制一个Item条目就会调用一次getView方法
     *
     * @param item 数据源对象
     * @param position 数据源的position
     * @return item条目对象
     */
    public LItem getListViewItemView(T item, int position) {
        int stylesCount = styles.size();
        for (int i = stylesCount - 1; i >= 0; i--) {
            LItem<T> delegate = styles.valueAt(i);
            if (delegate.isForViewType(item, position)) {
                return delegate;
            }
        }
        throw new IllegalArgumentException(
                "在数据源中指定的位置没有相匹配的ListViewItemManager，position=" + position);
    }

    public int getItemViewLayoutId(T item, int position) {
        return getListViewItemView(item, position).getItemViewLayoutId();
    }
}
